Attribute VB_Name = "PN"
Option Explicit
Function CALC_EM(Zn_1 As Range, Zn_2 As Range, Mul_2 As Range) As Double
Application.Volatile

 Dim Frst As String
 Dim Scnd As String
 Dim AdrRow, AdrCol As Integer

 Frst = Zn_1.Value - Zn_2.Value
 Scnd = Mul_2.Value

 If (Frst = "") Then Frst = "0"
 If (Scnd = "") Then Scnd = "1"

 If (Asc(Left(Scnd, 1)) >= 48 And Asc(Left(Scnd, 1)) <= 57) Then
  Scnd = "*" + Scnd
 Else
    If (FindOpenBrackets(Scnd) = True) Then
      Frst = "(" + Frst
    End If
 End If

 Frst = Frst + Scnd

 Frst = fPrepare(Frst)
 CALC_EM = CDbl(CalcPolishNotation(Frst))
End Function
Function CALC(Mul_1 As Range, Mul_2 As Range) As Double

 Application.Volatile

 Dim Frst As String
 Dim Scnd As String
 Dim AdrRow, AdrCol As Integer


 Frst = Mul_1.Value
 Scnd = Mul_2.Value

 If (Frst = "") Then Frst = "0"
 If (Scnd = "") Then Scnd = "1"

 If (Asc(Left(Scnd, 1)) >= 48 And Asc(Left(Scnd, 1)) <= 57) Then
  Scnd = "*" + Scnd
 Else
    If (FindOpenBrackets(Scnd) = True) Then
      Frst = "(" + Frst
    End If
 End If

 Frst = Frst + Scnd

 Frst = fPrepare(Frst)
 CALC = CDbl(CalcPolishNotation(Frst))

End Function
Function CALC_PZ(POPC1 As Range, Cena As Double, Priznak As Range, Kolvo As Range) As Double

  Dim POPC1tmp, Znak, NeZnak As String
  Dim Pr As String
  Dim sCena As String
  Dim Tmp As String
  Dim sKolvo As String

  CALC_PZ = 0#

  POPC1tmp = POPC1.Value
  sKolvo = Kolvo.Value
  sCena = CStr(Cena)

  If POPC1tmp = "" Then POPC1tmp = "1"

  If Len(POPC1tmp) > 1 Then
    Znak = Mid(POPC1tmp, 1, 1)
    NeZnak = Right(POPC1tmp, Len(POPC1tmp) - 1)
  Else
    NeZnak = POPC1tmp
  End If

  If Asc(Left(NeZnak, 1)) < 48 Or Asc(Left(NeZnak, 1)) > 57 Then Exit Function

  If Znak <> "+" And Znak <> "-" And Znak <> "*" And Znak <> "/" Then
     Znak = "*"
     NeZnak = POPC1tmp
  End If

  Pr = Priznak.Value

  If Znak = "+" Or Znak = "-" Then

     If Pr <> "IsMater" And Pr <> "IsMash" Then
        CALC_PZ = Cena
        Exit Function
     End If

     Tmp = sCena + Znak + "((" + NeZnak + ")" + "*" + sKolvo + ")"

  ElseIf Znak = "*" Or Znak = "-" Then
    Tmp = sCena + Znak + "(" + NeZnak + ")"
  Else
    Exit Function
  End If

  Tmp = fPrepare(Replace(Tmp, ".", ","))
  CALC_PZ = CDbl(CalcPolishNotation(Tmp))

End Function
Function FindOpenBrackets(Strng As String) As Boolean
 Dim i As Integer

 FindOpenBrackets = False
 For i = 1 To Len(Strng)
  If (Mid(Strng, i, 1) = "(") Then
   FindOpenBrackets = False
   Exit For
  End If
  If (Mid(Strng, i, 1) = ")") Then
   FindOpenBrackets = True
   Exit For
  End If
 Next i
End Function
Function fPrepare(sFormula As String) As String
  Dim OUTSTRING As String
  Dim STACK As String
  Dim Tmp As String
  Dim SYMB As String
  Dim LString As Integer
  Dim i As Integer

  LString = Len(sFormula)
  SYMB = GET_TOK(sFormula)
  Do

    If (SYMB = "(" Or SYMB = ")" Or _
        SYMB = "+" Or SYMB = "-" Or _
        SYMB = "*" Or SYMB = "/") Then

        If (OUTSTRING = "") Then
          Call POP(STACK, SYMB)
          SYMB = GET_TOK(sFormula)
          GoTo NextGeneration
        End If
        If (SYMB = "(") Then
          Call POP(STACK, SYMB)
          SYMB = GET_TOK(sFormula)
          GoTo NextGeneration
        ElseIf (SYMB = ")") Then
          Do
            Tmp = PUSH(STACK)
            If (Tmp <> "(") Then
              OUTSTRING = OUTSTRING + Tmp + "|"
            Else
              Exit Do
            End If
          Loop While (STACK <> "")
          SYMB = GET_TOK(sFormula)
          GoTo NextGeneration
        ElseIf (SYMB = "+" Or SYMB = "-") Then
          Tmp = Mid(STACK, 1, 1)
          If (Tmp = "+" Or Tmp = "-" Or Tmp = "*" Or Tmp = "/") Then
            Do
              Tmp = PUSH(STACK)
              If (Tmp = "+" Or Tmp = "-" Or Tmp = "*" Or Tmp = "/") Then
                OUTSTRING = OUTSTRING + Tmp + "|"
              Else
                 Exit Do
              End If
            Loop While (STACK <> "")
          Else
            Call POP(STACK, SYMB)
            SYMB = GET_TOK(sFormula)
          End If
        ElseIf (SYMB = "*" Or SYMB = "/") Then
         Tmp = Mid(STACK, 1, 1)
          If (Tmp = "*" Or Tmp = "/") Then
           Do
              Tmp = Mid(STACK, 1, 1)
              If (Tmp = "*" Or Tmp = "/") Then
                OUTSTRING = OUTSTRING + Tmp + "|"
                Tmp = PUSH(STACK)
              Else
                Exit Do
              End If
            Loop While (STACK <> "")
          End If
            Call POP(STACK, SYMB)
          SYMB = GET_TOK(sFormula)
        End If
    ElseIf (Asc(SYMB) >= 48 And Asc(SYMB) <= 57) Then
        Do
          OUTSTRING = OUTSTRING + SYMB
          SYMB = GET_TOK(sFormula)
          If SYMB = "$" Then
            OUTSTRING = OUTSTRING + "|"
            GoTo EndFunk
          End If
        Loop While ((Asc(SYMB) >= 48 And Asc(SYMB) <= 57) Or SYMB = ",")
        OUTSTRING = OUTSTRING + "|"
    End If
NextGeneration:
  Loop While sFormula <> "" Or SYMB <> "$"

EndFunk:
Do
  SYMB = GET_TOK(STACK)
  OUTSTRING = OUTSTRING + SYMB + "|"
  If (SYMB = "(") Then
    OUTSTRING = "ERROR"
    SYMB = "$"
  End If
Loop While SYMB <> "$"

fPrepare = OUTSTRING
End Function
Function PUSH(ByRef STACK As String) As String

 PUSH = Mid(STACK, 1, 1)
 STACK = Right(STACK, Len(STACK) - 1)

End Function
Sub POP(ByRef STACK As String, SYMB As String)
 STACK = SYMB + STACK
End Sub
Function GET_TOK(ByRef Symbols As String)
  If (Symbols <> "") Then
    GET_TOK = Mid(Symbols, 1, 1)
  Else
    GET_TOK = "$"
    Exit Function
  End If
  Symbols = Right(Symbols, Len(Symbols) - 1)
End Function
Function CalcPolishNotation(P_String As String) As Double

Dim STACK(0 To 10) As Double
Dim SYMB As String
Dim NUM As Double
Dim P_STACK As Integer
Dim Tmp1, Tmp2 As Double
P_STACK = 0

SYMB = GET_SYMBOL(P_String)
Do
 If ((Asc(Mid(SYMB, 1, 1)) >= 48 And Asc(Mid(SYMB, 1, 1)) <= 57)) Then
   If P_STACK > 10 Then
    MsgBox "ÎØÈÁÊÀ"
   Else
    STACK(P_STACK) = CDbl(Replace(SYMB, ".", ","))
    P_STACK = P_STACK + 1
   End If
 Else
  If (SYMB = "*") Then
     STACK(P_STACK - 2) = STACK(P_STACK - 2) * STACK(P_STACK - 1)
   ElseIf (SYMB = "/") Then
     STACK(P_STACK - 2) = STACK(P_STACK - 2) / STACK(P_STACK - 1)
   ElseIf (SYMB = "+") Then
     STACK(P_STACK - 2) = STACK(P_STACK - 2) + STACK(P_STACK - 1)
   ElseIf (SYMB = "-") Then
     STACK(P_STACK - 2) = STACK(P_STACK - 2) - STACK(P_STACK - 1)
   End If
   STACK(P_STACK - 1) = 0#
   P_STACK = P_STACK - 1
   SYMB = ""
 End If
SYMB = GET_SYMBOL(P_String)
Loop While (P_String <> "$" And P_String <> "")
CalcPolishNotation = STACK(P_STACK - 1)
End Function
Function GET_SYMBOL(ByRef P_String As String) As String
Dim TmpSymb As String
  Do
    TmpSymb = GET_TOK(P_String)
    If TmpSymb <> "|" Then
      GET_SYMBOL = GET_SYMBOL + TmpSymb
    Else
      Exit Do
    End If
  Loop While TmpSymb <> ""

End Function

